/**
 * @file head.h
 * @brief 云台及发射机构控制核心头文件
 * @details 定义云台（pitch/yaw轴）、发射机构（摩擦轮/拨盘）的结构体、控制模式枚举、状态宏及通信接口
 * @author WeiFan Qiu (qiuweifan0523@faxmail.com)
 * @version 1.0
 * @date 2025-08-08
 * 
 * @copyright Copyright (c) 2025  邱伟凡
 * 
 * @par 修改日志:
 *  2025-08-08  初始版本，定义基础控制结构
 * 
 * @bug 待解决问题:
 * - 发射机构射速闭环逻辑待完善
 */
#ifndef GIMBAL_H
#define GIMBAL_H

#include "stdint.h"          // 标准整数类型定义
#include "motor.h"           // 电机驱动结构体（依赖DJI_Motor_t）
#include "dm_imu.h"          // 惯性测量单元（IMU）数据接口
#include "HI229.h"           // 陀螺仪传感器驱动（假设为HI229型号）
#include "state.h"           // 系统状态管理（依赖QWF_State_t）
#include "QWF_Include.h"     // 通用功能库（如限幅、滤波函数）
#include "communicate.h"     // 通信协议定义（依赖控制模式枚举）
#include "pid.h"
/**********************************************************************************/
/* 发射机构参数 */
#define fire_persent_to_knob	0.7f  // 双摩擦轮转速需超过最大值的70%时，拨盘才启动供弹
#define fire_diff	500              // 左右摩擦轮转速允许的最大差值（防止卡弹）
/* 云台机械限位 */
#define PITCH_MAX	(30.0f)         // Pitch轴最大角度（向上30度）
#define PITCH_MIN	(-15.0f)        // Pitch轴最小角度（向下15度）

/* 注：原云台模式/发射模式枚举已移至 communicate.h 中 */
// typedef enum{//云台的模式
// 	gimbal_stop=0,		//云台停止
// 	gimbal_yes,			//不控制云台，改控制底盘角速度
// 	gimbal_normal,		//云台正常控制旋转
// 	gimbal_vision,		//视觉跟随
// 	gimbal_vision_test,	//视觉跟随测试
// 	gimbal_mode_num		//模式数量
// }gimbal_mode_e;
// typedef enum{//发弹机构的模式
// 	fire_stop=0,		//不发射
// 	fire_yes,			//正常发射
// 	fire_knob_stop,		//仅拨盘不动
// 	fire_once,			//单发(电机n圈拨一次)
// 	fire_continuous,	//连发
// 	shoot_mode_num		//模式数量
// }shoot_mode_e;

/**
 * @brief 云台控制函数指针类型（根据模式调用不同控制逻辑）
 */
typedef void(*gimbal_ctrl_func_t)(void);

/**
 * @brief 发射机构控制函数指针类型（根据发射模式调用不同逻辑）
 */
typedef void(*shoot_ctrl_func_t)(void);

/**
 * @brief 云台及发射机构全局结构体（核心控制数据）
 */
typedef struct{
    struct{// 分功能模块
        struct{// 云台控制模块
            const gimbal_ctrl_func_t ctrl_func[gimbal_mode_num];  // 模式-控制函数映射表（根据模式调用对应控制逻辑）
            gimbal_mode_e mode[2];                                   // 当前云台模式（来自communicate.h）
            struct{// Pitch轴控制参数
                struct{// 目标值（理论设定）
                    float angle;  // 目标角度（单位：度）
                    float w;      // 目标角速度（单位：度/秒）
                    int16_t out;  // 电机输出控制量（PWM/电流）
                }target;
                DJI_Motor_t motor;  // 电机驱动结构体（包含通信配置、反馈数据）
                struct{// 实际测量值（融合后）
                    float angle;  // 实际角度（单位：度）
                    float w;      // 实际角速度（单位：度/秒）
                }my;
            }pitch;
            struct{// Yaw轴控制参数（与Pitch轴结构对称）
                struct{// 目标值
                    float angle;
                    float w;
                    int16_t out;
                }target;
                DJI_Motor_t motor;
                struct{// 实际测量值
                    float angle;
                    float w;
                }my;
            }yaw;
        }gimbal;
        struct{// 发射机构控制模块
            const shoot_ctrl_func_t ctrl_func[shoot_mode_num];  // 发射模式-控制函数映射表
            shoot_mode_e mode[2];                                   // 当前发射模式（来自communicate.h）
            struct{// 摩擦轮控制参数
                struct{// 左摩擦轮
                    struct{// 目标值
                        float v;      // 目标转速（单位：rpm）
                        int16_t out;  // 电机输出控制量
                    }target;
                    DJI_Motor_t motor;  // 电机驱动结构体
                }l;
                struct{// 右摩擦轮（与左摩擦轮结构对称）
                    struct{// 目标值
                        float v;
                        int16_t out;
                    }target;
                    DJI_Motor_t motor;
                }r;
                struct{// 射速闭环控制参数
                    _Bool use;          // 是否启用射速闭环
                    int8_t over_num;    // 转速超限次数（用于故障保护）
                    float v_max;        // 闭环计算的最大允许转速
                }speed_loop;
                struct{// 斜坡控制参数（平滑加减速）
                    float now;          // 当前斜坡值
                    float max;          // 斜坡最大值
                }ramp;
                enum{// 摩擦轮状态（是否准备好发射）
                    unready=0,          // 未就绪（转速未达标）
                    ready=1             // 就绪（转速达标）
                }state;
            }fire;
            struct{// 拨盘控制参数
                struct{// 目标值
                    float angle;  // 目标角度（单位：机械角度）
                    float v;      // 目标转速（单位：rpm）
                    float v_max;  // 最大允许转速
                    int16_t out;  // 电机输出控制量
                }target;
                DJI_Motor_t motor;  // 电机驱动结构体
                struct{// 热量闭环控制参数（防止过热）
                    _Bool use;          // 是否启用热量闭环
                    int8_t over_num;    // 温度超限次数
                    float v_max;        // 闭环计算的最大允许转速
                }heat_loop;
            }knob;
        }shoot;
    }part;
//	struct{
//	
//	}sys;
//	struct{
//	
//	}Judge;	
	head_pid_t* pid;
}head_t;

extern head_t* head;  // 全局云台结构体指针（外部可访问）

/**
 * @brief 更新云台状态（如角度、转速等测量值）
 * @details 需周期调用，从传感器/电机反馈中获取最新数据并融合计算
 */
void Gimbal_State_Updata(void);

/******************宏定义（简化代码编写）*********/
// 云台模式快捷访问
#define gimbal_mode						(head->part.gimbal.mode)
// 发射模式快捷访问
#define shoot_mode						(head->part.shoot.mode)

// Pitch轴参数快捷访问（目标值/测量值）
#define pitch_angle_target				(head->part.gimbal.pitch.target.angle)
#define pitch_angle_meas_motor       	(head->part.gimbal.pitch.motor.rx_meas.angle[2])  // 电机反馈的机械角度（8192线编码器）
#define pitch_angle_meas_gyro       	(dm_imu->euler[0])                                // IMU反馈的欧拉角（单位：度）
#define pitch_angle_meas        		(head->part.gimbal.pitch.my.angle)                // 融合后的实际角度（单位：度）
#define pitch_w_target					(head->part.gimbal.pitch.target.w)
#define pitch_w_meas_motor				(head->part.gimbal.pitch.motor.rx_meas.rpm)       // 电机反馈的转速（单位：rpm）
#define pitch_w_meas_gyro				(hi2xx->gyr[1])                                   // 陀螺仪反馈的角速度（单位：度/秒）
#define pitch_w_meas        			(head->part.gimbal.pitch.my.w)                    // 融合后的实际角速度（单位：度/秒）

// Yaw轴参数快捷访问（与Pitch轴对称）
#define yaw_angle_target 				(head->part.gimbal.yaw.target.angle)
#define yaw_angle_meas_motor       		(head->part.gimbal.yaw.motor.rx_meas.angle[2])
#define yaw_angle_meas_gyro        		(dm_imu->euler[1])
#define yaw_angle_meas        			(head->part.gimbal.yaw.my.angle)
#define yaw_w_target               		(head->part.gimbal.yaw.target.w)
#define yaw_w_meas_motor          		(head->part.gimbal.yaw.motor.rx_meas.rpm)
#define yaw_w_meas_gyro          		(dm_imu->gyo[2])
#define yaw_w_meas          			(head->part.gimbal.yaw.my.w)

// 摩擦轮参数快捷访问
#define fire_l_v_target					(head->part.shoot.fire.l.target.v)
#define fire_l_v_meas					(head->part.shoot.fire.l.motor.rx_meas.rpm)
#define fire_r_v_target					(head->part.shoot.fire.r.target.v)
#define fire_r_v_meas       			(head->part.shoot.fire.r.motor.rx_meas.rpm)

// 拨盘参数快捷访问
#define knob_angle_target				(head->part.shoot.knob.target.angle)
#define knob_angle_meas      			(head->part.shoot.knob.motor.rx_meas.angle[2])
#define knob_v_target              		(head->part.shoot.knob.target.v)
#define knob_v_meas          			(head->part.shoot.knob.motor.rx_meas.rpm)

#ifdef STATE_H  // 包含状态管理头文件时启用故障保护逻辑
/**
 * @brief 发送GM6020电机控制数据（带状态保护）
 * @param motor_where 电机位置（如pitch/yaw）
 * @details 根据电机状态（正常/丢失/过热）设置输出，并将控制量写入CAN总线缓冲区
 */
#define send_data_head_gm6020(motor_where)/*全都用小写*/\
do{\
    switch(qwf_state->head.motor.gimbal.motor_where.state){\
        case gm6020_ok:	break;\
        case gm6020_lose:		head->part.gimbal.motor_where.target.out=0;break;\
        case gm6020_too_hot_1:	head->part.gimbal.motor_where.target.out=0;break;\
        case gm6020_too_hot_2:	head->part.gimbal.motor_where.target.out=0;break;\
        case gm6020_i_over_max:	head->part.gimbal.motor_where.target.out=0;break;\
    }\
    /* 将控制量写入CAN总线发送缓冲区（高8位+低8位）*/\
    head->part.gimbal.motor_where.motor.config.tx_adress[0]=(head->part.gimbal.motor_where.target.out>>8);\
    head->part.gimbal.motor_where.motor.config.tx_adress[1]=(head->part.gimbal.motor_where.target.out);	\
}while(0);

/**
 * @brief 发送C620电机控制数据（带状态保护）
 * @param motor_where 电机位置（如fire.l/fire.r）
 * @details 根据电机状态（正常/丢失/电流超限）设置输出，并将控制量写入CAN总线缓冲区
 */
#define send_data_head_c620(motor_where)/*全都用小写*/\
do{\
    switch(qwf_state->head.motor.shoot.motor_where.state){\
        case c620_ok:break;\
        case c620_lose:			head->part.shoot.motor_where.target.out=0;break;\
        case c620_i_over_max:	head->part.shoot.motor_where.target.out=0;break;\
    }\
    /* 将控制量写入CAN总线发送缓冲区（高8位+低8位）*/\
    head->part.shoot.motor_where.motor.config.tx_adress[0]=(head->part.shoot.motor_where.target.out>>8);\
    head->part.shoot.motor_where.motor.config.tx_adress[1]=(head->part.shoot.motor_where.target.out);	\
}while(0);
#else  // 未包含状态管理头文件时，仅发送原始控制量（无故障保护）
#define send_data_head_gm6020(motor_where)\
do{\
    head->part.gimbal.motor_where.motor.config.tx_adress[0]=(head->part.gimbal.motor_where.target.out>>8);\
    head->part.gimbal.motor_where.motor.config.tx_adress[1]=(head->part.gimbal.motor_where.target.out);	\
}while(0);

#define send_data_head_c620(motor_where)\
do{\
    head->part.shoot.motor_where.motor.config.tx_adress[0]=(head->part.shoot.motor_where.target.out>>8);\
    head->part.shoot.motor_where.motor.config.tx_adress[1]=(head->part.shoot.motor_where.target.out);	\
}while(0);
#endif

#endif
